#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NumPy 性能优化示例
演示如何编写高效的NumPy代码
"""

import numpy as np
import time

def compare_vectorization():
    """对比向量化与循环的性能"""
    print("=== 向量化 vs 循环性能对比 ===")
    
    size = 1000000
    x = np.random.randn(size)
    y = np.random.randn(size)
    
    # NumPy向量化操作
    start = time.time()
    result_vec = x * y + np.sin(x) + np.cos(y)
    vec_time = time.time() - start
    
    # 模拟Python循环（用小样本估算）
    start = time.time()
    sample_size = min(1000, size)
    result_loop = []
    for i in range(sample_size):
        result_loop.append(x[i] * y[i] + np.sin(x[i]) + np.cos(y[i]))
    loop_time = (time.time() - start) * (size / sample_size)
    
    print(f"数组大小: {size}")
    print(f"向量化时间: {vec_time:.6f}秒")
    print(f"循环估算时间: {loop_time:.6f}秒")
    print(f"性能提升: {loop_time/vec_time:.1f}倍")

def memory_efficiency():
    """内存效率优化"""
    print("\n=== 内存效率优化 ===")
    
    # 选择合适的数据类型
    large_array = np.arange(1000000)
    
    print("数据类型对内存的影响:")
    print(f"int64: {large_array.astype(np.int64).nbytes / 1024**2:.1f} MB")
    print(f"int32: {large_array.astype(np.int32).nbytes / 1024**2:.1f} MB")
    print(f"int16: {large_array.astype(np.int16).nbytes / 1024**2:.1f} MB")
    
    # 使用视图而不是复制
    arr = np.arange(1000000).reshape(1000, 1000)
    
    start = time.time()
    view = arr[::2, ::2]  # 视图
    view_time = time.time() - start
    
    start = time.time()
    copy = arr[::2, ::2].copy()  # 复制
    copy_time = time.time() - start
    
    print(f"\n视图创建时间: {view_time:.6f}秒")
    print(f"复制创建时间: {copy_time:.6f}秒")
    print(f"内存共享: {np.shares_memory(arr, view)}")

def broadcasting_optimization():
    """广播优化技巧"""
    print("\n=== 广播优化技巧 ===")
    
    # 预分配数组
    size = (1000, 1000)
    
    # 低效方式：重复创建数组
    start = time.time()
    result1 = np.zeros(size)
    for i in range(100):
        temp = np.random.randn(*size)
        result1 += temp
    inefficient_time = time.time() - start
    
    # 高效方式：预分配和重用
    start = time.time()
    result2 = np.zeros(size)
    temp_array = np.empty(size)
    for i in range(100):
        np.random.randn(*size, out=temp_array)
        result2 += temp_array
    efficient_time = time.time() - start
    
    print(f"重复创建数组时间: {inefficient_time:.3f}秒")
    print(f"预分配数组时间: {efficient_time:.3f}秒")
    print(f"性能提升: {inefficient_time/efficient_time:.1f}倍")

def main():
    """运行所有性能示例"""
    print("NumPy 性能优化技巧")
    print("=" * 40)
    
    compare_vectorization()
    memory_efficiency()
    broadcasting_optimization()
    
    print("\n=== 性能优化总结 ===")
    print("1. 使用向量化操作而不是循环")
    print("2. 选择合适的数据类型")
    print("3. 使用视图而不是复制")
    print("4. 预分配数组")
    print("5. 利用广播机制")

if __name__ == "__main__":
    main() 